﻿/*
 * Author:  hammer
 * CreateTime: 2018/9/30 16:32:34
 * Module: Implement
 * 主要功能：dll方案
 *
 */
using System.Collections;
using System.Collections.Generic;
using UnityEngine;


/**
*  class MegaRtcEngine 以单例的形式提供接口
 */

namespace MGAudioEngine
{

    public sealed class MGAudioEngine
    {
        //private float _conElapsedTime = 0;
        //private int _pollConnectCache = 0;
        private ConnectState __connectState = ConnectState.Init;
        #region Singleton
        private static MGAudioEngine _instance;
        public static MGAudioEngine Instance
        {
            get
            {
                if (_instance == null)
                    _instance = new MGAudioEngine();
                return _instance;
            }
        }

        public static void Destroy()
        {
            if (_instance == null)
                return;

            _instance = null;
        }
        #endregion

        #region Callback

        public delegate void AuthenSuccessDelegate();
        public AuthenSuccessDelegate OnAuthenSuccess;

        public delegate void AuthenFailDelegate();
        public AuthenFailDelegate OnAuthenFail;

        public delegate void JoinRoomSuccessDelegate(long roomId);
        public JoinRoomSuccessDelegate OnJoinRoomSuccess;

        public delegate void JoinRoomFailDelegate(ConnectError error);
        public JoinRoomFailDelegate OnJoinRoomFail;
        
        public delegate void QuitRoomSuccessDelegate();
        public QuitRoomSuccessDelegate OnQuitRoomSuccess;

        public delegate void ConnectLostDelegate(ConnectError error);
        public ConnectLostDelegate OnConnectLost;

        public delegate void UpdateSpeakerInfoDelegate(SpeakerInfo speakerInfo);
        public UpdateSpeakerInfoDelegate OnUpdateSpeakerInfo;

        public delegate void UserJoinedChannelDelegate(UserChannel userChannel);
        public UserJoinedChannelDelegate OnUserJoinedChannel;
        
        public delegate void ReceiveChatMessage(ChatMessage chatMessage);
        public ReceiveChatMessage OnReceiveChatMessage;

        public delegate void ReceiveInfoMessage(InfoMessage infoMessage);
        public ReceiveInfoMessage OnReceiveInfoMessage;

        //call when connectState changed
        public delegate void ConnectStateChanged(ConnectState newState,ConnectState oldState);
        public ConnectStateChanged OnConnectStateChanged;
        #endregion

        #region API

#if UNITY_IOS && !UNITY_EDITOR
        private IMGAudioEngine _mgAudioEngineImp = new MGAudioEngineDllImp();
#elif UNITY_ANDROID && !UNITY_EDITOR
        private IMGAudioEngine _mgAudioEngineImp = new MGAudioEngineNativeImp();
#elif UNITY_EDITOR
       private IMGAudioEngine _mgAudioEngineImp = new MGAudioEngineUniImp();
#endif

        public ConnectState GetConnectState
        {
            get{return __connectState;}
        }
        public ConnectState SetConnectState
        {
            set
            {
                if (value != __connectState)
                {
                    ConnectState oldState = __connectState;
                    __connectState = value;
                    OnConnectStateChanged(__connectState, oldState);
                }
            }
        }

        public void AuthApp(string appId,string appKey,string deviceToken)
        {
            if(GetConnectState == ConnectState.Authenticating)
                return;
            _mgAudioEngineImp.AuthApp(appId,appKey,deviceToken);
        }

        public void InitAduioSetting()
        {
            _mgAudioEngineImp.InitAduioSetting();
        }

        public void UpdateAudioSetting()
        {
            _mgAudioEngineImp.UpdateAudioSetting();
        }

        public void JoinRoom(long roomId,string userName)
        {
            if(GetConnectState == ConnectState.Connecting)
                return;
            SetConnectState = ConnectState.Connecting;
            _mgAudioEngineImp.JoinRoom(roomId,userName);
        }

        public void CreateRoom(string userName)
        {
            if (GetConnectState == ConnectState.Connecting)
                return;
            SetConnectState = ConnectState.Connecting;
            _mgAudioEngineImp.CreateRoom(userName);
        }

        public void RejoinRoom(long roomId)
        {
            if (GetConnectState == ConnectState.Connecting)
                return;
            SetConnectState = ConnectState.Connecting;
            _mgAudioEngineImp.ReJoinRoom(roomId);
        }

        public void OpenMic()
        {
            if (_mgAudioEngineImp.OpenMic() == 1)
            {
                Debuger.Log("open mic success");
            }
            else
            {
                Debuger.Log("open mic faile ");
            }

        }

        public void CloseMic()
        {
            if (_mgAudioEngineImp.CloseMic() == 1)
            {
                Debuger.Log("close mic success");
            }
            else
            {
                Debuger.Log("close mic faile ");
            }
        }

        public void OpenSpeaker()
        {
            if (_mgAudioEngineImp.OpenSpeaker() == 1)
            {
                Debuger.Log("open speaker success");
            }
            else
            {
                Debuger.Log("open speaker faile");
            }
        }

        public void CloseSpeaker()
        {
            if (_mgAudioEngineImp.CloseSpeaker() == 1)
            {
                Debuger.Log("close speaker success");
            }
            else
            {
                Debuger.Log("close speaker faile");
            }
        }

        public void SendTextMessage(string msg, bool isTree = true,int channelId = 0)
        {
            _mgAudioEngineImp.SendTextMessage(msg,channelId,isTree);
        }

        public void QuitRoom(long roomId)
        {
            if (GetConnectState == ConnectState.Quiting)
                return;
            SetConnectState = ConnectState.Quiting;
            _mgAudioEngineImp.QuitRoom(roomId);
        }

        public void DeallocMGAudio()
        {
            _mgAudioEngineImp.DeallocMGAudio();
            _mgAudioEngineImp = null;
            __connectState = ConnectState.Init;
        }



        /// <summary>
        /// loop handle message,must call in Update
        /// </summary>
        public void Polling()
        {
            switch(__connectState){
                case ConnectState.Init:
                    break;
                default:
                    this.PollMessage();
                    break;
            }
          
        }

        //private void PollConnect()
        //{
        //    int connect = _mgAudioEngineImp.GetIsConnect();
        //    //connect
        //    if (_pollConnectCache == 0 && connect == 1)
        //    {
        //        _pollConnectCache = connect;
        //        _connectState = ConnectState.Connected;
        //        OnJoinRoomSuccess();
        //        return;
        //    }
        //    //connect
        //    else if (_pollConnectCache == 1 && connect == 1)
        //    {
        //        _connectState = ConnectState.Connected;
        //        return;
        //    }
        //    //disconnect
        //    else if (_pollConnectCache == 1 && connect == 0)
        //    {
        //        _pollConnectCache = connect;
        //        //leve room
        //        if (_connectState == ConnectState.Quiting)
        //        {
        //            _connectState = ConnectState.Quited;
        //            OnQuitRoomSuccess();
        //        }
        //        else
        //        {
        //            _connectState = ConnectState.LostConnect;
        //            OnConnectLost(ConnectError.Unknow);
        //        }
        //        return;
        //    }

        //    //timeout
        //    if (_connectState == ConnectState.Connecting)
        //    {
        //        _conElapsedTime += Time.unscaledDeltaTime;
        //        if (_conElapsedTime >= TimeoutThres)
        //        {
        //            _connectState = ConnectState.LostConnect;
        //            _connectState = 0;
        //            OnConnectLost(ConnectError.Timeout);
        //        }
        //    }
        //}


        void PollMessage()
        {
            string message = _mgAudioEngineImp.GetMessage();
            if(string.IsNullOrEmpty(message))
                return;

            Debuger.Log(string.Format("unity rec native msg:{0}", message));
            char   msgKey  = message[0];
            string msgBody = message.Substring(1);
            switch (msgKey)
            {
                case PollMsg.AudioState:
                    int audioState ;
                    if (int.TryParse(msgBody, out audioState))
                    {
                        HandleAudioState(audioState);
                    }
                    else
                    {
                        Debuger.LogError(string.Format("PollMsg.AudioState: can not parse int from msgBody:{0}", msgBody));
                    }
                    break;
                case PollMsg.ChatMessage:
                    ChatMessage chatMessage = JsonUtility.FromJson<ChatMessage>(msgBody);
                    OnReceiveChatMessage(chatMessage);
                    break;
                case PollMsg.InfoMessage:
                    InfoMessage infoMessage = JsonUtility.FromJson<InfoMessage>(msgBody);
                    OnReceiveInfoMessage(infoMessage);
                    break;
                case PollMsg.JoinRoomSucc:
                    long roomId;
                    if (long.TryParse(msgBody, out roomId))
                    {
                        SetConnectState = ConnectState.Connected;
                        OnJoinRoomSuccess(roomId);
                    }
                    else
                    {
                        SetConnectState = ConnectState.LostConnect;
                        OnJoinRoomFail(ConnectError.RoomIdError);
                        Debuger.LogError(string.Format("PollMsg.JoinRoomSucc: can not parse long from msgBody:{0}", msgBody));
                    }
                    break;
                case PollMsg.SpeakInfo:
                    SpeakerInfo speakerInfo = JsonUtility.FromJson<SpeakerInfo>(msgBody);
                    OnUpdateSpeakerInfo(speakerInfo);
                    break;
                case PollMsg.SpeakState:
                    //Debuger.Log("SpeakState(暂时未用到) msgBody:" + msgBody);
                    break;
                case PollMsg.UserJoinedChannel:
                    UserChannel userChannel = JsonUtility.FromJson<UserChannel>(msgBody);
                    OnUserJoinedChannel(userChannel);
                    break;
            }
        }

        /// <summary>
        /// 处理从native获得的audioState
        /// </summary>
        /// <param name="audioState"></param>
        void HandleAudioState(int audioState)
        {
            switch ((AudioState)audioState)
            {
                case AudioState.CONNECTION_LOST: //连接丢失
                    this.SetConnectState = ConnectState.LostConnect;
                    OnConnectLost(ConnectError.LostConnect);
                    break;
                case AudioState.DISCONNECTED:     //连接已被销毁
                    this.SetConnectState = ConnectState.ConnectDestroyed;
                    OnConnectLost(ConnectError.ConnectDestroyed);
                    break;
                case AudioState.JION_ROOM_FAILURE:     //加入房间失败
                    this.SetConnectState = ConnectState.LostConnect;
                    OnJoinRoomFail(ConnectError.JoinRoomFail);
                    break;
                case AudioState.CREATE_ROOM_FAILURE:     //创建房间失败
                    this.SetConnectState = ConnectState.LostConnect;
                    OnJoinRoomFail(ConnectError.CreateRoomFail);
                    break;
                case AudioState.NOT_FIND_ROOM:     //未找到房间
                    this.SetConnectState = ConnectState.LostConnect;
                    OnJoinRoomFail(ConnectError.NotFoundRoom);
                    break;
                case AudioState.UNAUTETHENTICATION: //未认证
                    this.SetConnectState = ConnectState.UnAuthenticatiion;
                    if (this.GetConnectState == ConnectState.Connecting)
                    {
                        OnJoinRoomFail(ConnectError.UnAuthen);
                    }
                    OnAuthenFail();
                    break;
                case AudioState.AUTETHENTICATED:     //认证成功
                    this.SetConnectState = ConnectState.Authenticated;
                    OnAuthenSuccess();
                    break;
            }
        }

        #endregion
    }




   

}
